<template>
  <div class="ai-search-page">
    <div class="search-chat-card">
      <div class="answer-content" ref="answerRef" :class="chatCondition.files.length ? 'answer-content_files' : ''">
        <div class="chat-item" v-for="chat in chatHistory" :key="chat.id">
          <div class="user-content">
            <div class="user-text">
              {{ chat.user }}
            </div>
          </div>
          <div class="aispire-content">
            <div class="ai-avatar">
              <div class="avatar"></div>
            </div>
            <div class="ai-text" v-if="!chat.loading">
              <!--              {{ chat.aispire }}-->
              <div class="reasoning-box" :class="chat.reasoningExpand ? 'expand' : ''" v-if="chat.reasoning">
                <div class="thinking-box" v-if="chat.status === ChatStatusEnum.Thinking">
                  <i class="iconfont icon-tuili-copy loading"></i>
                  <span>推理搜索中……</span>
                </div>
                <div class="thinking-box" v-else>
                  <i class="iconfont icon-duigouwancheng"></i>
                  <span>已完成推理</span>
                </div>
                <el-icon class="arrow-icon" @click="handleChatExpandReasoning(chat)"><ArrowDown /></el-icon>
                <div class="thinking-text">
                  <MarkdownComp :content="chat.reasoning"></MarkdownComp>
                </div>
              </div>
              <MarkdownComp :content="chat.aispire"></MarkdownComp>
              <div class="opt-box">
                <div class="opt-item" @click="handleCopy(chat)">
                  <i class="iconfont icon-copy"></i>
                  <span>复制</span>
                </div>
                <div class="opt-item" @click="handleRetry(chat)">
                  <i class="iconfont icon-ai22"></i>
                  <span>重新生成</span>
                </div>
              </div>
            </div>
            <i v-else class="iconfont icon-jiazaizhong loading"></i>
          </div>
        </div>
      </div>
      <div class="input-box">
        <!--        <el-button type="default" size="large" class="new-topic-btn" @click="handleNewTopic">-->
        <!--          <template #icon>-->
        <!--            <i class="iconfont icon-xinduihua"></i>-->
        <!--          </template>-->
        <!--          开启新对话-->
        <!--        </el-button>-->
        <el-input class="text-area" type="textarea" :rows="2" v-model="questionStr" size="large" clearable placeholder="请输入你想问的问题"  @keypress.enter="handleSendQuestion(null)"></el-input>
        <div class="option-box" :class="chatCondition.files.length ? 'option-box_file' : ''">
          <div class="lf-box">
            <el-select v-model="chatCondition.model" placeholder="请选择模型" style="width: 200px">
              <el-option-group
                  v-for="group in modelList"
                  :key="group.platform"
                  :label="group.name">
                <el-option
                    v-for="item in group.list"
                    :key="group.platform +'[#]'+item.code"
                    :label="group.name + '：' +item.label"
                    :value="group.platform +'[#]'+item.code"/>
              </el-option-group>
            </el-select>
<!--            <el-dropdown class="opt-item llm-item" @command="handleSelectModel">-->
<!--              <el-button size="small" :type="chatCondition.model ? 'primary' : 'default'">-->
<!--                <span v-if="chatCondition.model === 'dsr1'">DeepSeek R1</span>-->
<!--                <span v-if="chatCondition.model === 'dsv3'">DeepSeek V3</span>-->
<!--                <el-icon class="el-icon&#45;&#45;right"><arrow-down /></el-icon>-->
<!--              </el-button>-->
<!--              <template #dropdown>-->
<!--                <el-dropdown-menu>-->
<!--                  <el-dropdown-item command="dsr1">DeepSeek R1</el-dropdown-item>-->
<!--                  <el-dropdown-item command="dsv3">DeepSeek V3</el-dropdown-item>-->
<!--                </el-dropdown-menu>-->
<!--              </template>-->
<!--            </el-dropdown>-->
            <el-switch size="small" v-model="chatCondition.online_search" active-text="联网搜索" />
          </div>
          <div class="rt-box">
<!--            <div class="opt-item upload-file-item">-->
<!--              <el-tooltip-->
<!--                  class="box-item"-->
<!--                  effect="dark"-->
<!--                  :content="uploading ? '文件上传解析中' : '支持最大50MB的pdf、doc、docx、txt、xls、xlsx、cvs等文件上传'"-->
<!--                  placement="top">-->
<!--                <el-upload-->
<!--                    v-if="!uploading"-->
<!--                    :show-file-list="false"-->
<!--                    class="upload-demo"-->
<!--                    :accept="accept"-->
<!--                    action="/aispire/topic/upload_files"-->
<!--                    :data="uploadData"-->
<!--                    name="files"-->
<!--                    :before-upload="handleFileBeforeUpload"-->
<!--                    :on-success="handleUploadSuccess">-->
<!--                  <i class="iconfont icon-fujian"></i>-->
<!--                </el-upload>-->
<!--                <i v-else class="iconfont icon-jiazaizhong loading"></i>-->
<!--              </el-tooltip>-->
<!--            </div>-->
            <div class="opt-item run-item">
              <el-button type="primary" circle v-if="chatStatus === ChatStatusEnum.Stop" @click="handleSendQuestion(null)">
                <template #icon>
                  <i class="iconfont icon-kaishi1"></i>
                </template>
              </el-button>
              <el-button type="danger" v-else @click="handleStop" circle>
                <template #icon>
                  <i class="iconfont icon-stop-full"></i>
                </template>
              </el-button>
            </div>
          </div>
        </div>
        <div class="file-content scrollbar-y" v-if="chatCondition.files.length">
          <div class="file-item" v-for="(file, index) in chatCondition.files" :key="file.id">
            <div class="file-icon">
              <div class="icon image-icon" v-if="'image'=== file.typeStr"></div>
              <div class="icon excel-icon" v-if="'excel' === file.typeStr"></div>
              <div class="icon txt-icon" v-if="'txt' === file.typeStr"></div>
              <div class="icon pdf-icon" v-if="'pdf' === file.typeStr"></div>
              <div class="icon word-icon" v-if="'word' === file.typeStr"></div>
            </div>
            <div class="file-info">
              <div class="name">{{file.name}}</div>
              <div class="detail">{{file.sizeStr}}</div>
            </div>
            <i class="iconfont icon-shanchu3" @click="handleDelUploadFile(index)"></i>
          </div>
        </div>

      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, nextTick, computed} from 'vue'
import {ElMessage} from 'element-plus'
import {ArrowDown} from "@element-plus/icons-vue";
import html2canvas from 'html2canvas';
import MarkdownComp from '../../components/markdown-comp.vue'
import {copyText, transformFileSize, uuid} from "~/common/utils.js";
import api from '../../api/index.js'
import common from "~/common/common.js";
import {fetchEventSource} from '@microsoft/fetch-event-source'

const user = common.getLocalUser()
const uid = user.userId
const currentTopicId = ref('')
const fileList = ref([])
const modelList = ref([])
const uploading = ref(false) // 文件上传中
const accept = 'application/pdf,application/vnd.ms-excel,text/csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/plain,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
const uploadData = computed(() => {
  return {
    uid,
    topic_id: currentTopicId.value
  }
})


const getFileCommonType = (type) => {
  if (type.indexOf('pdf') > -1) {
    return 'pdf'
  }
  if (type.indexOf('excel') > -1 || type.indexOf('csv') > -1 || type.indexOf('sheet') > -1) {
    return 'excel'
  }
  if (type.indexOf('image') > -1) {
    return 'image'
  }
  if (type.indexOf('text') > -1) {
    return 'txt'
  }
  if (type.indexOf('word') > -1) {
    return 'word'
  }

}
const handleDelUploadFile = (index) => {
  chatCondition.value.files.splice(index, 1)
}
const handleFileBeforeUpload = (file) => {
  // console.log('handleFileBeforeUpload', file)
  const typeArr = accept.split(',')
  if (!typeArr.includes(file.type)) {
    ElMessage.error('仅支持doc、docx、pdf、txt、xls、xlsx等文档格式文件')
    return false
  }
  if (file.size > 50 * 1024 * 1024) {
    ElMessage.error('单个文件大小限制50MB以内')
    return false
  }
  uploading.value = true
  return true
}
const handleUploadSuccess = (res, file) => {
  // console.log('handleUploadSuccess', file)
  if (res.uploaded_files && res.uploaded_files.length) {
    const id = uuid(12)
    const sizeStr = transformFileSize(file.size)
    chatCondition.value.files.push({
      id,
      sizeStr: sizeStr,
      size: file.size,
      type: file.raw.type,
      typeStr: getFileCommonType(file.raw.type),
      name: file.name,
      path: res.uploaded_files[0]
    })
  } else {
    ElMessage.error('文件上传失败')
  }
  uploading.value = false

}

const ChatStatusEnum = {
  Start: -1, // 开始提问
  Thinking: 1,// 思考推理中
  Loading: 2,// 答案返回中
  Stop: 3,// 停止
}
const chatStatus = ref(ChatStatusEnum.Stop)
const chatCondition = ref({
  model: '',
  files: [],
  online_search: false,
})
const answerRef = ref()
const questionStr = ref('')
const chatHistory = ref([])
const EventStreamContentType = 'text/event-stream; charset=utf-8'
const handleSelectModel = (model) => {
  chatCondition.value.model = model
}
const questionSubmit = (text, index, apiToken) => {
  return new Promise((resolve, reject) => {

    chatCondition.value.files = []
    const ctrlAbout = new AbortController();
    const modelObjArr = chatCondition.value.model.split('[#]')
    fetchEventSource(`/ai-repost/stream/${modelObjArr[0]}/chat`, {
      method: 'POST',
      headers: {
        "Content-Type": 'application/json',
        'Accept': '*/*',
        'api-token': apiToken,
      },
      openWhenHidden: true,
      body: JSON.stringify({
        content: text,
        model: modelObjArr[1],
        userId: window.__testUserId// 写死的test用户的userId
      }),
      signal: ctrlAbout.signal,
      onmessage(event) {
        // 在这里操作流式数据
        // console.log('message', event)
        const chatItem = chatHistory.value[index]
        chatItem.loading = false
        if (chatStatus.value !== ChatStatusEnum.Stop) {
          try {
            const data = JSON.parse(event.data)
            if (Object.hasOwn(data, 'reasoning')) {
              // 推理中
              chatItem.status = ChatStatusEnum.Thinking
              chatItem.reasoning += data.reasoning
              nextTick(() => {
                answerRef.value.scrollTop = answerRef.value.scrollHeight - answerRef.value.offsetHeight
              })
            }
            if (Object.hasOwn(data, 'answer')) {
              // 给出答案中
              chatItem.status = ChatStatusEnum.Loading
              chatItem.aispire += data.answer
              nextTick(() => {
                answerRef.value.scrollTop = answerRef.value.scrollHeight - answerRef.value.offsetHeight
              })
            }
          } catch(e){}
        } else {
          ctrlAbout.abort()
          handleStop()
          resolve()
        }
      },
      onopen(response){
        console.log('open', response)
        if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
          //return // everything's good
        } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
          // client-side errors are usually non-retriable:
          reject()
          throw new Error()
        } else {
          reject()
          throw new Error()
        }
      },
      onclose(e) {
        console.log('close', e)
        // 关闭流
        // 中断流式返回
        ctrlAbout.abort()
        handleStop()
        resolve()
      },
      onerror(error) {
        // 返回流报错
        console.info(error);
        // 中断流式返回
        ctrlAbout.abort()
        handleStop()
        reject()
        throw error // 直接抛出错误，避免反复调用
      }
    })
  })
}
const handleSendQuestion = async (str) => {
  const text = str || questionStr.value
  if (!text) {
    return
  }
  if (!chatCondition.value.model) {
    ElMessage.error('请先选择模型')
    return
  }
  let apiToken = ''
  const res = await api.getApiToken({userId: window.__testUserId})
  if (res?.data?.token) {
    apiToken = res.data.token
  }
  if (!apiToken) {
    ElMessage.error('API Token获取失败')
    return
  }
  const id = uuid(12)
  chatStatus.value = ChatStatusEnum.Start
  questionStr.value = ''
  chatHistory.value.push({
    id,
    user: text,
    reasoning: '', // 推理结果
    aispire: '', // 答案结果
    loading: true, // 标记请求是否有回调了
    reasoningExpand: true,
    status: ChatStatusEnum.Start,
  })
  const len = chatHistory.value.length
  questionSubmit(text,len - 1, apiToken).then(() => {
    nextTick(() => {
      answerRef.value.scrollTop = answerRef.value.scrollHeight - answerRef.value.offsetHeight
    })
  })
  nextTick(() => {
    answerRef.value.scrollTop = answerRef.value.scrollHeight - answerRef.value.offsetHeight
  })
}
const handleChatExpandReasoning = (chat) => {
  chat.reasoningExpand = !chat.reasoningExpand
}

const handleStop = () => {
  chatStatus.value = ChatStatusEnum.Stop
  chatHistory.value[chatHistory.value.length - 1].loading = false
}
const getSnap = () => {
  const element = answerRef.value
  const width = element.offsetWidth
  const height = element.scrollHeight
  console.log(width, height)
  html2canvas(element, {
    backgroundColor: '#ffffff',
    width,
    height,
    windowWidth: width*1.2,
    windowHeight: height,
    // scale: 1,
  }).then(function(canvas) {
    document.body.appendChild(canvas);
    const url = canvas.toDataURL("image/png");
    const link = document.createElement('a')
    link.href = url
    link.download = 'image.png' // 下载文件的名称
    link.click()
  });
}

const handleCopy = (item) => {
  copyText(item.aispire)
  ElMessage.success('已复制到剪贴板')
}
const handleRetry = (item) => {
  handleSendQuestion(item.user)
}
const getAllModelList = () => {
  modelList.value = []
  api.getModelList().then((res) => {
    if (res.data) {
      modelList.value = res.data
    }
  })
}
getAllModelList()
</script>

<style scoped lang="scss">


</style>
